#include <stdio.h>
#include <math.h>
#include <malloc.h>
#include <sndfile.h>
#include <AL/al.h>
#include <AL/alc.h>
#include <AL/alut.h>
#include <termios.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

int kbhit();

#define OUTPUT_WAVE_FILE "Capture.wav"
#define OUTPUT_WAVE_FILE_RAW "CaptureCrudo"
#define BUFFERSIZE 4410

const int SRATE = 22050;
ALint nMostres;

int main(int argc, char *argv[])
{
double freq;
const ALCchar *szDefaultCaptureDevice;
FILE *pFile;
ALchar* Buffer[BUFFERSIZE];
int i, error;
ALuint buffer, fuente;
ALint sourceState;

freq = SRATE;

// Inicialización (véase listado 2)
// Hardware
ALCcontext *pContext = alcGetCurrentContext();
ALCdevice *pDevice = alcGetContextsDevice(pContext);
if (alcIsExtensionPresent(pDevice, "ALC_EXT_CAPTURE") == AL_FALSE)
{
printf("Fallo al detectar extensión de captura.\n"); return 0;
}
szDefaultCaptureDevice = alcGetString(NULL,ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
printf("\nDispositivo de captura por defecto es '%s'\n\n", szDefaultCaptureDevice);

ALCdevice *device;
device = alcCaptureOpenDevice(szDefaultCaptureDevice, freq, AL_FORMAT_MONO16,
BUFFERSIZE);
printf("Dipositivo de captura: '%s' esta abierto\n\n", alcGetString(device,
ALC_CAPTURE_DEVICE_SPECIFIER));

// Ficheros: RAW
FILE * pFileRAW = fopen(OUTPUT_WAVE_FILE_RAW, "wb");
// y WAVE mediante libsndfile.
SF_INFO info;
info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
info.channels = 1;
info.samplerate = SRATE;
SNDFILE *pFileWAVE = sf_open(OUTPUT_WAVE_FILE, SFM_WRITE, &info);

// Captura del audio (véase listado 3)
alcCaptureStart(device);

float bloq = info.channels * 16/8; // bytes por bloque
while (!kbhit()) {
alcGetIntegerv(device, ALC_CAPTURE_SAMPLES, BUFFERSIZE, &nMostres);
printf("nMostress: %d\n", nMostres);

if (nMostres > (BUFFERSIZE / bloq))
{
alcCaptureSamples(device, Buffer, BUFFERSIZE/bloq);
fwrite(Buffer,BUFFERSIZE , 1, pFileRAW);
sf_writef_short(pFileWAVE, (short*)Buffer, BUFFERSIZE/bloq);

}

else{

alcCaptureSamples(device, (ALCvoid *)Buffer, nMostres);
fwrite(Buffer, nMostres, 1, pFileRAW);
sf_writef_short(pFileWAVE, (short*)Buffer, nMostres/bloq);

}
}
// Cerrar la aplicación (véase listado 4)
//cerramos todo: Hard. ...
alcCaptureStop(device);
alcCaptureCloseDevice(device);

// y ficheros: RAW
fclose( pFileRAW );
// …y WAVE
sf_write_sync( pFileWAVE );
sf_close( pFileWAVE );
printf("\nSaved captured audio data to '%s'\n", OUTPUT_WAVE_FILE);

alcMakeContextCurrent(NULL);
alcDestroyContext(pContext);
alcCloseDevice(pDevice);
return EXIT_SUCCESS;

}

// Función para detectar que se ha pulsado cualquier tecla en terminales UNIX.
int kbhit()
{
struct termios oldt, newt;
int ch;
int oldf;

tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
ch = getchar();
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
fcntl(STDIN_FILENO, F_SETFL, oldf);

if(ch != EOF)
{
ungetc(ch, stdin);
return 1;
}
return 0;

}



